package org.admin.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import core.data.DataHandle;
import org.admin.entity.domain.Role;
import org.admin.entity.domain.User;
import org.admin.entity.domain.UserRole;
import org.admin.entity.vo.UserFetchVo;
import org.admin.entity.vo.UserQueryVo;
import org.admin.mapper.UserRoleMapper;
import org.admin.entity.dto.UserDto;
import org.admin.mapper.UserMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class UserService {
    @Autowired
    UserMapper mapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    // 添加用户
    @Transactional
    public void create(DataHandle<UserDto, ?> handle) {
        UserDto params = handle.getParams();
        boolean doUpdate = true;
        Date now = new Date();
        User user;
        MPJLambdaWrapper<User> userQuery = MPJWrappers.lambdaJoin(User.class);
        if(params.getId() != null && params.getId() != 0){
            // 更新
            user = mapper.selectById(params.getId());
            if(user == null){
                handle.failure("id", "指定用户不存在");
                return;
            }
            if(!params.getPassword().equals(DigestUtils.md5Hex(user.getPassword()))){
                user.setPassword(DigestUtils.md5Hex(params.getPassword()));
            }
            userQuery.ne(User::getId, user.getId());
        }else{
            user = new User();
            user.setPassword(DigestUtils.md5Hex(params.getPassword()));
            user.setCreatedAt(now);
            doUpdate = false;
        }
        // 校验用户名
        if(userQuery.eq(User::getUsername, params.getUsername()).count() > 0){
            handle.failure("username", "用户名已存在");
            return ;
        }
        // 校验角色
        List<Integer> roles = params.getRoleIds();
        if(MPJWrappers.lambdaJoin(Role.class)
                .in("id", params.getRoleIds())
                .count()!= params.getRoleIds().size()){
            handle.failure("roleIds", "绑定角色不存在");
            return;
        }
        user.setEmail(params.getEmail());
        user.setUsername(params.getUsername());
        user.setNickname(params.getNickname());
        user.setPicture(params.getPicture());
        user.setGenderWith(params.getGender()? User.GENDER.MALE: User.GENDER.FEMALE);
        user.setUpdatedAt(now);
        if(doUpdate){
            mapper.updateById(user);
        }else{
            mapper.insert(user);
        }
        List<Integer> roleIds = new ArrayList<>(params.getRoleIds());
        // 校验分表
        MPJLambdaWrapper<UserRole> userRoleQuery = new MPJLambdaWrapper<>(UserRole.class);
        List<UserRole> userRoleList = userRoleQuery.disableLogicDel()
                .in("role_id", params.getRoleIds())
                .eq("user_id", user.getId())
                .list(UserRole.class);

        for(UserRole item : userRoleList){
            if(roleIds.contains(item.getRoleId())){
                userRoleMapper.recover(item.getId());
                roleIds.remove(item.getRoleId());
            }else{
                userRoleMapper.deleteById(item);
            }
        }
        // 插入数据
        for(Integer id : roleIds){
            userRoleMapper.insert(new UserRole() {{
                setUserId(user.getId());
                setRoleId(id);
                setCreatedAt(now);
                setUpdatedAt(now);
            }});
        }
        handle.success();
    }

    public void query(DataHandle<UserDto, IPage<UserQueryVo>> handle) {
        UserDto params = handle.getParams();
        MPJLambdaWrapper<User> query = new MPJLambdaWrapper<>();
        query.select(User::getId, User::getNickname, User::getPicture, User::getGender, User::getEmail)
            .selectFunc(() -> "GROUP_CONCAT(%s SEPARATOR ',')", Role::getName, UserQueryVo::getRoleNames);
        // GROUP_CONCAT(detail_table.name SEPARATOR ',') AS names
        if(params.getRoleId() != null && params.getRoleId() != 0){
            query.innerJoin(UserRole.class,  UserRole::getUserId, User::getId)
                    .innerJoin(Role.class, Role::getId, UserRole::getRoleId)
                    .eq(UserRole::getRoleId, params.getRoleId());
        }else{
            query.leftJoin(UserRole.class,  UserRole::getUserId, User::getId)
                    .leftJoin(Role.class, Role::getId, UserRole::getRoleId);
        }
        query.groupBy(User::getId)
                .orderByDesc(User::getCreatedAt);

        if(params.getNickname() != null){
            query.like(User::getNickname, "%" + params.getNickname() + "%");
        }
        if(params.getGender() != null){
            query.like(User::getGender, params.getGender() ? User.GENDER.MALE.getValue(): User.GENDER.FEMALE.getValue());
        }

        IPage<UserQueryVo> list = mapper.selectJoinPage(new Page<>(params.getCurrent(), params.getSize()), UserQueryVo.class, query);

        handle.success(list);
    }

    public void fetch(DataHandle<UserDto, UserFetchVo> handle) {
        UserDto params = handle.getParams();
        User user = mapper.selectById(params.getId());
        if(user == null){
            handle.failure("id", "指定用户不存在");
            return;
        }
        List<Integer> roleIds = MPJWrappers.lambdaJoin(UserRole.class)
                .select(UserRole::getRoleId)
                .eq(UserRole::getUserId, user.getId())
                .list(HashMap.class)
                .stream()
                .map(item -> (Integer) item.get("role_id"))
                .toList();
        handle.success(new UserFetchVo(){{
            setId(user.getId());
            setUsername(user.getUsername());
            setPassword(DigestUtils.md5Hex(user.getPassword()));
            setNickname(user.getNickname());
            setPicture(user.getPicture());
            setGender(user.getGender());
            setEmail(user.getEmail());
            setRoleIds(roleIds);
        }});
    }
    @Transactional
    public void remove(DataHandle<UserDto, ?> handle) {
        UserDto params = handle.getParams();
        if(MPJWrappers.lambdaJoin(User.class)
                .in(User::getId, params.getIds())
                .count() != params.getIds().size()){
            handle.failure("ids", "选择了不存在的用户");
            return;
        }
        mapper.deleteBatchIds(params.getIds());
        // 删除分表
        userRoleMapper.delete(JoinWrappers.delete(UserRole.class)
                .in(UserRole::getUserId, params.getIds()));

        handle.success();
    }
}
